package ScanLineAlghorithms.RectanglesUnion;

import java.util.Stack;

import DataModel.SegmentTree.SegmentTreeNode;
import ScanLineAlghorithms.RectanglesUnion.TreeNodeAdditionalData.STATUS;
/**
 * Class models computation of additional data stored in segment tree.
 * @author Guy
 *
 */
public class Contribute {
	/**
	 * 
	 * @param begin - begining of processed edge
	 * @param end - end of processed edge
	 * @param root - root of segment tree
	 * @return - endpoints of scan line , represents its current status
	 */
	public static Stack activate(long begin, long end ,SegmentTreeNode root) {
		Stack verEdgesPoints = contr( begin, end ,root);
	
		return verEdgesPoints;
		
	}
	
	private static  STATUS getStatus(SegmentTreeNode v) {
		return ((TreeNodeAdditionalData)v.getGenericData()).getStatus();
	}
	

	private static Stack contr(long begin, long end ,SegmentTreeNode root) {
		//		 if the edge is downward or backward direction
		if (begin>end) {
			long t = end;
			end = begin;
			begin = t;
		}
		
		Stack<Long> edges  = new Stack<Long>();
		Stack<SegmentTreeNode> s = new Stack<SegmentTreeNode>();
		s.push(root);
		while (!s.isEmpty()){
			SegmentTreeNode v = s.pop();
			if (getStatus(v) != STATUS.FULL) {
				if (begin <= v.getBegining() && v.getEnd() <= end && getStatus(v) == STATUS.EMPTY) {
					if (!edges.isEmpty()) {
						if (edges.peek()==v.getBegining()) {
							edges.pop();
						} else {
							edges.push(v.getBegining());
						}
					} else {	
						edges.push(v.getBegining());
					}
					edges.push(v.getEnd());
				} else {
					if (v.rightSon() != null ) {
						if (v.rightSon().getBegining() <= end) {
							s.push(v.rightSon());
						}
					}
					if (v.leftSon()  != null ) {
						if (begin <= v.leftSon().getEnd()) {
							s.push(v.leftSon());
						}		
					}
				}
			} 
				
		}
		return edges;
	}
	
}
	

